home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 March
/
CHIP Mart 1997.iso
/
prg
/
Gameport
/
GAMDEMO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-30
|
19KB
|
737 lines
/*
// GAMDEMO.C
//
// Game port demo program for the Gport game port library.
//
// Compiled and linked with Borland C++ v2.00
//
// Copyright (c) 1991 Bri Productions
//
*/
#include "gport.h"
#include <stdlib.h>
#include <bios.h>
#include <graphics.h>
#include <alloc.h>
#include <stdio.h>
#include <stdarg.h>
#include <dos.h>
#define AXIS 0 /* GamAxis()/GamStick switch */
#define limit(n,max,min) (n) > (max) ? (max) : ((n) < (min) ? (min) :(n))
/*
//-------------------------------------
//
// screen coordinates, sizes, etc.
//
//-------------------------------------
*/
#define BASE_X 640 /* base with of the screen */
#define BASE_Y 480 /* base with of the screen */
#define XREF 9 /* X scaling reference */
#define YREF 35 /* X scaling reference */
#define OAX 170 /* x origin of joystick a */
#define OAY 175 /* y origin of joystick a */
#define OBX 470 /* x origin of joystick b */
#define OBY 175 /* y origin of joystick b */
#define JR 135 /* joystick radius */
#define TSIZE 5 /* size of tic marks */
#define TSPACE 10 /* spacing of tic marks */
#define TNUM 13 /* number of tic marks */
#define HSIZE 5 /* cross hair size */
#define BAY 350 /* y center of a buttons */
#define BBY 350 /* y center of b buttons */
#define BSPACE 100 /* x space between buttons */
#define BR 20 /* button radius */
#define BON 1 /* button on */
#define BOFF 0 /* button off */
#define GAIN 7 /* gain divisor for Gport */
#define BIOS_GAIN 14 /* gain multiplier for bios*/
#define Y_COORD_OFF 235 /* Y coordinate offset */
#define JAY_COORD (OAY) + Y_COORD_OFF
#define JBY_COORD (OAY) + Y_COORD_OFF
#define TEXT_Y 370 /* text y position */
/*
//-------------------------------------
//
// Text justification
//
//-------------------------------------
*/
#define J_LEFT 0 /* left justified text */
#define J_CENTER 1 /* center justified text */
#define J_RIGHT 2 /* right justified text */
/*
//-------------------------------------
//
// keystrokes
//
//-------------------------------------
*/
#define F1 0x3B00
#define F2 0x3C00
#define F3 0x3D00
#define F4 0x3E00
#define F5 0x3F00
#define F6 0x4000
#define F7 0x4100
#define F8 0x4200
#define F9 0x4300
#define F10 0x4400
#define ESC 0x011B
/*
//-------------------------------------
//
// function prototypes
//
//-------------------------------------
*/
void Init (void);
void Uninit (void);
void PutAxis (int x, int y);
void PutButton (int x, int off);
void CrossHair (int x, int y);
void Button (byte status);
void PutCoord (int x, int y, int just, signed value);
void gputs (int x, int y, int color, int just, char *str);
void gerase (int x, int y, int color, int just, char *str);
/*
//-------------------------------------
//
// global variables
//
//-------------------------------------
*/
void *old_image[2]; /* image behind the cross hair */
int Xasp, Yasp; /* X and Y aspect ratios */
int bios_ax0, bios_ay0; /* bios values for joystick A */
int bios_bx0, bios_by0; /* bios values for joystick B */
/*
//-------------------------------------
//
// default colors (vga/ega)
//
//-------------------------------------
*/
int color = YELLOW; /* default color */
int bcolor = RED; /* button color */
int vcolor = YELLOW; /* values color */
int tcolor = GREEN; /* text color */
int hcolor = WHITE; /* cross hair color */
int bkcolor = DARKGRAY; /* background color */
/*
//-------------------------------------
//
// function macros
//
//-------------------------------------
*/
#define X(a) (a)*XREF/Xasp /* X scaling */
#define Y(a) (a)*YREF/Yasp /* Y scaling */
/*
//-------------------------------------
//
// main()
//
//-------------------------------------
*/
void main(void)
{
signed ax, ay, bx, by; /* joystick coordinates */
signed old_ax, old_ay, old_bx, old_by; /* old joystick coordinates */
byte bstat; /* button status */
byte old_bstat = 0; /* old button status */
int key = 0; /* keystroke */
int gport = 1; /* gport mode flag */
union REGS regs; /* CPU registers for bios */
char *mode[] = { "Bios", "Gport" }; /* mode text */
char *cmode[] = { "Real", "Mean" };
byte center = 0;
Init();
old_ax = old_ay = old_bx = old_by =0x7fff;
while(key != ESC)
{
/* If we are not in Gport mode, call the bios to */
/* get the joystick positions. */
if(!gport)
{
regs.h.ah = 0x84;
regs.x.dx = 1;
int86(0x15, ®s, ®s);
ax = ( regs.x.ax - bios_ax0) * BIOS_GAIN;
ay = (-regs.x.bx + bios_ay0) * BIOS_GAIN;
bx = ( regs.x.cx - bios_bx0) * BIOS_GAIN;
by = (-regs.x.dx + bios_by0) * BIOS_GAIN;
ax = limit(ax,1000,-1000);
ay = limit(ay,1000,-1000);
bx = limit(bx,1000,-1000);
by = limit(by,1000,-1000);
}
/* If we are in Gport mode, call GamAxis or GamStick to */
/* get the joystick position for joystick A */
if(gport)
{
#if AXIS
ax = GamAxis(JAX);
ay = GamAxis(JAY);
#else
GamAxes(JA, &ax, &ay);
#endif
}
/* If either coordinate has changed since the last time */
/* it was checked, the screen must be updated with the */
/* new value */
if(ax != old_ax)
{
PutCoord(OAX, JAY_COORD, textwidth(" +0000"), ax);
old_ax = ax;
}
if(ay != old_ay)
{
PutCoord(OAX, JAY_COORD, - textwidth("Y = "), ay);
old_ay = ay;
}
/* Apply the gain divisor to the new coordinates and */
/* update the cross hair. */
ax /= GAIN; ay /= GAIN;
CrossHair(OAX + ax, OAY - ay);
/* If we are in Gport mode, call GamAxis or GamStick to */
/* get the joystick position for joystick B */
if(gport)
{
#if AXIS
bx = GamAxis(JBX);
by = GamAxis(JBY);
#else
GamAxes(JB, &bx, &by);
#endif
}
/* If either coordinate has changed since the last time */
/* it was checked, the screen must be updated with the */
/* new value */
if(bx != old_bx)
{
PutCoord(OBX, JBY_COORD, textwidth(" +0000") , bx);
old_bx = bx;
}
if(by != old_by)
{
PutCoord(OBX, JBY_COORD, - textwidth("Y = "), by);
old_by = by;
}
/* Apply the gain divisor to the new coordinates and */
/* update the cross hair. */
bx /= 7; by /= GAIN;
CrossHair(OBX + bx, OBY - by);
/* If we are in Gport mode, use GamButton. Otherwise */
/* make the call to the bios. */
if(gport)
bstat = GamButton();
else
{
regs.h.ah = 0x84;
regs.x.dx = 0;
int86(0x15, ®s, ®s);
bstat = regs.h.al ^ 0xf0;
}
/* Check the button status has changed from the */
/* last call. If it has, update the screen. */
if(bstat != old_bstat)
{
Button(bstat);
old_bstat = bstat;
}
/* If the spacebar has been pressed, toggle modes. The */
/* screen is updated to reflect the new mode and a call */
/* to GamButton is made to clear the button status. */
if(bioskey(1))
{
key = bioskey(0);
switch(key)
{
case F1:
GamCalAxis(JAX, GamRawAxis(JAX));
break;
case F2:
GamCalAxis(JAY, GamRawAxis(JAY));
break;
case F3:
GamCalAxis(JBX, GamRawAxis(JBX));
break;
case F4:
GamCalAxis(JBY, GamRawAxis(JBY));
break;
case F5:
if(gport)
{
gerase(BASE_X/2, TEXT_Y + 20, bkcolor, J_CENTER, *(cmode + center));
center ^= 1;
GamCenter(center);
gputs(BASE_X/2, TEXT_Y + 20, tcolor, J_CENTER, *(cmode + center));
break;
}
break;
case F6:
gerase(BASE_X/2, TEXT_Y, bkcolor, J_CENTER, *(mode + gport));
gport ^= 1;
gputs(BASE_X/2, TEXT_Y, tcolor, J_CENTER, *(mode + gport));
if(!gport)
gerase(BASE_X/2, TEXT_Y + 20, bkcolor, J_CENTER, *(cmode + center));
else
gputs(BASE_X/2, TEXT_Y + 20, tcolor, J_CENTER, *(cmode + center));
Button(bstat);
break;
case F7:
GamOpen();
regs.h.ah = 0x84;
regs.x.dx = 1;
int86(0x15, ®s, ®s);
bios_ax0 = regs.x.ax;
bios_ay0 = regs.x.bx;
bios_bx0 = regs.x.cx;
bios_by0 = regs.x.dx;
gerase(BASE_X/2, TEXT_Y + 20, bkcolor, J_CENTER, *(cmode + center));
break;
}
}
}
Uninit();
}
/*
//-------------------------------------
//
// initialize
//
//-------------------------------------
*/
void Init(void)
{
int mode; /* display mode */
int i; /* iterations */
int driver = DETECT; /* display driver */
union REGS regs; /* registers for bios */
/* Initialize the game port for Gport and the bios */
if(!GamOpen())
{
puts("\nGame port not detected");
exit(1);
}
regs.h.ah = 0x84;
regs.x.dx = 1;
int86(0x15, ®s, ®s);
bios_ax0 = regs.x.ax;
bios_ay0 = regs.x.bx;
bios_bx0 = regs.x.cx;
bios_by0 = regs.x.dx;
/* Detect and initialize the graphics display */
detectgraph(&driver,&mode);
switch(driver)
{
case CGA:
mode = CGAC0;
color = CGA_YELLOW;
bcolor = CGA_RED;
vcolor = CGA_YELLOW;
tcolor = CGA_GREEN;
hcolor = CGA_RED;
bkcolor = DARKGRAY;
registerbgidriver(CGA_driver);
break;
case EGAMONO:
color = LIGHTGRAY;
bcolor = LIGHTGRAY;
tcolor = LIGHTGRAY;
vcolor = BLACK;
hcolor = WHITE;
registerbgidriver(EGAVGA_driver);
break;
case HERCMONO:
bcolor = WHITE;
vcolor = BLACK;
hcolor = WHITE;
bkcolor = BLACK;
registerbgidriver(Herc_driver);
break;
default:
registerbgidriver(EGAVGA_driver);
break;
}
registerbgifont(small_font);
initgraph(&driver,&mode,0);
Xasp = BASE_X * XREF / (getmaxx() + 1);
Yasp = BASE_Y * YREF / (getmaxy() + 1);
cleardevice();
setbkcolor(bkcolor);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
/* Draw our stuff on the screen */
gputs(OAX, 15, tcolor, J_CENTER, "Joystick A");
gputs(OBX, 15, tcolor, J_CENTER, "Joystick B");
setcolor(color);
PutAxis(OAX, OAY);
PutAxis(OBX, OBY);
for(i=-BSPACE/2; i<BSPACE; i+=BSPACE)
{
PutButton(OAX + i, BAY);
PutButton(OBX + i, BBY);
}
gerase(BASE_X/2, TEXT_Y, bkcolor, J_CENTER, "Gport");
gputs(BASE_X/2, TEXT_Y, tcolor, J_CENTER, "Gport");
gputs(BASE_X/2, TEXT_Y + 70, tcolor, J_CENTER, "Press ESC to quit");
setcolor(color);
}
/*
//-------------------------------------
//
// un-initialize
//
//-------------------------------------
*/
void Uninit(void)
{
GamClose();
closegraph();
free(old_image[0]);
free(old_image[1]);
exit(0);
}
/*
//-------------------------------------
//
// Draw the axes for a joystick
//
//-------------------------------------
*/
void PutAxis(int x, int y)
{
int i;
static j = 0;
/* Draw the horizontal axis */
line(X(x - JR), Y(y), X(x + JR), Y(y));
for(i=TSPACE; i<TNUM*(TSPACE*2+1); i+=TSPACE)
{
moveto(X(x - TSPACE*(TNUM+1) + i), Y(y - TSIZE));
linerel(0, Y(TSIZE * 2));
}
/* Draw the vertical axis */
line(X(x), Y(y - JR), X(x), Y(y + JR));
for(i=TSPACE; i<TNUM*(TSPACE*2 + 1); i+=TSPACE)
{
moveto(X(x - TSIZE), Y(y - TSPACE*(TNUM+1) + i));
linerel(X(TSIZE * 2), 0);
}
gputs(x, y + Y_COORD_OFF, color, J_CENTER, "X = Y = ");
/* Allocate memory for storing the image behind the cross */
/* hair, and store the initial image behind the initial cross */
/* hair. Because this memory is only allocated once and the */
/* same area on different parts of the screen may need a */
/* different amount of memory, twice the approximate memory */
/* needed is allocated just to be safe. */
old_image[j] = malloc(imagesize(0, 0, X(HSIZE * 2), Y(HSIZE * 2)) * 2);
getimage(X(x - HSIZE), Y(y - HSIZE), X(x + HSIZE + 1), Y(y + HSIZE), old_image[j]);
CrossHair(x, y);
j++;
}
/*
//-------------------------------------
//
// put cross hair at x,y
//
//-------------------------------------
*/
void CrossHair(int x, int y)
{
static i = 1;
static int old_x[2] = { OAX , OBX }; /* old crosshair for joystick B */
static int old_y[2] = { OAY , OBY }; /* old crosshair for joystick A */
int old_color; /* current color storage */
/* Restore the old image behind the cross hair, saving the */
/* new coordinates for the next call. By XORing 'i' with 1, we */
/* flip flop between the 2 joystick */
i ^= 1;
if(x == *(old_x + i) && y == *(old_y + i))
return;
/* If the coordinate has not changed there is no need to */
/* update the screen. */
putimage(X(*(old_x + i) - HSIZE), Y(*(old_y + i) - HSIZE), *(old_image + i), 0);
getimage(X(x - HSIZE), Y(y - HSIZE), X(x + HSIZE + 1), Y(y + HSIZE), *(old_image + i));
/* Draw the new cross hair */
old_color = getcolor();
setcolor(hcolor);
moveto(X(x), Y(y - HSIZE));
linerel(0, Y(HSIZE * 2));
moverel(X(-HSIZE), Y(-HSIZE));
linerel(X(HSIZE * 2), 0);
setcolor(old_color);
*(old_x + i) = x;
*(old_y + i) = y;
}
/*
//-------------------------------------
//
// display a button
//
//-------------------------------------
*/
void PutButton(int x, int y)
{
circle(X(x), Y(y), X(BR));
circle(X(x), Y(y), X(BR - 3));
}
/*
//-------------------------------------
//
// display new button status
//
//-------------------------------------
*/
void Button(byte status)
{
int i = 0;
byte _button;
static byte button[4] = { 0, 0, 0, 0 };
int y[4] = { BAY, BAY, BBY, BBY };
int x[4] = { OAX - BSPACE / 2, OAX + BSPACE / 2,
OBX - BSPACE / 2, OBX + BSPACE / 2
};
/* Or the pending status with the current status to determine */
/* if a button has been pressed */
status |= (status >> 4);
/* Check each button for a change in it's state by shifting */
/* the bits right once each iteration and anding with 1, and */
/* then comparing it's new status with it's old status. If it's */
/* status has changed, redraw the button accordingly */
while(i < 4)
{
_button = status & 1;
if(button[i] != _button)
{
button[i] = _button;
setfillstyle(_button, bcolor);
fillellipse(X(x[i]), Y(y[i]), X(BR - 3), Y(BR - 3));
}
status >>= 1;
i++;
}
}
/*
//-------------------------------------
//
// put a coordinate value
//
//-------------------------------------
*/
void PutCoord(int x, int y, int just, signed value)
{
char str[80];
sprintf(str, "%+04d", value);
gerase(x, y, bcolor, just, str);
gputs(x, y, vcolor, just, str);
}
/*
//-------------------------------------
//
// graphics puts
//
//-------------------------------------
*/
void gputs(int x, int y, int color, int just, char *str)
{
switch(just)
{
case J_CENTER:
just = textwidth(str) / 2;
case J_LEFT:
break;
case J_RIGHT:
just = textwidth(str);
default:
break;
}
setcolor(color);
outtextxy(X(x) - just, Y(y), str);
setcolor(color);
}
/*
//-------------------------------------
//
// graphics erase
//
//-------------------------------------
*/
void gerase(int x, int y, int color, int just, char *str)
{
struct fillsettingstype old_set;
switch(just)
{
case J_CENTER:
just = textwidth(str) / 2;
case J_LEFT:
break;
case J_RIGHT:
just = textwidth(str);
}
getfillsettings(&old_set);
setfillstyle(SOLID_FILL, color);
bar(X(x) - just - 2, Y(y), X(x) + textwidth(str) - just + 1, Y(y) + textheight(str) + 3);
setfillstyle(old_set.pattern, old_set.color);
}